﻿#region License
/*Copyright (c) 2010 Andrew Collard (andrewcollard@hotmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
#endregion

using System.ComponentModel;
using System.IO;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using Microsoft.Practices.Unity;
using TorchView.Store;
using TorchView.Windows;

namespace TorchView.FileStore
{
  public class GameFileViewModel : INotifyPropertyChanged, IGameFileViewModel
  {
    private IUnityContainer _Container;
    private IFileStore _FileStore;
    private string _Filename;

    public string Filename
    {
      get { return _Filename; }
      set { _Filename = value; }
    }
    private bool _LocalExists;

    public GameFileViewModel(string filename, IFileStore fileStore, IGameFileView view, IUnityContainer container)
    {
      _Container = container;
      View = view;
      view.Model = this;
      _Filename = filename;
      _FileStore = fileStore;
      Name = Path.GetFileName(filename);
      _LocalExists = File.Exists(_Filename);

      _StoreFileCommand = new DirectCommand(ExecuteStoreFile, p => LocalExists);
      _EditCommentCommand = new DirectCommand(ExecuteEditComment, GameFileSelected);
      _DeleteFileCommand = new DirectCommand(ExecuteDeleteFile, GameFileSelected);
      _DownloadFileCommand = new DirectCommand(ExecuteDownloadFile, GameFileSelected);

      OnGameFilesChanged();
    }

    #region Properties
    public IGameFileView View { get; private set; }

    public string Name { get; private set; }
    public bool LocalExists
    {
      get { return _LocalExists; }
      private set
      {
        if (_LocalExists != value)
        {
          _LocalExists = value;
          OnPropertyChanged("LocalExists");
        }
      }
    }
    public CollectionView Files { get; private set; }
    #endregion

    #region Commands
    private DirectCommand _StoreFileCommand;
    public ICommand StoreFileCommand { get { return _StoreFileCommand; } }
    private DirectCommand _EditCommentCommand;
    public ICommand EditCommentCommand { get { return _EditCommentCommand; } }
    private DirectCommand _DeleteFileCommand;
    public ICommand DeleteFileCommand { get { return _DeleteFileCommand; } }
    private DirectCommand _DownloadFileCommand;
    public ICommand DownloadFileCommand { get { return _DownloadFileCommand; } }
    #endregion

    private void ExecuteStoreFile(object parameter)
    {
      var viewModel = _Container.Resolve<IEditCommentViewModel>(new PropertyOverride("Owner", Application.Current.MainWindow));
      if (viewModel.View.ShowDialog() ?? false)
      {
        _FileStore.Store(_Filename, viewModel.Comment);
        OnGameFilesChanged();
      }
    }

    private void ExecuteEditComment(object parameter)
    {
      var gameFile = Files.CurrentItem as FileBackup;
      if (gameFile != null)
      {
        var viewModel = _Container.Resolve<IEditCommentViewModel>(new PropertyOverride("Owner", Application.Current.MainWindow));
        viewModel.Comment = gameFile.Comments;
        if (viewModel.View.ShowDialog() ?? false)
        {
          _FileStore.UpdateComments(gameFile, viewModel.Comment);
          Files.Refresh();
        }
      }
    }

    private void ExecuteDeleteFile(object parameter)
    {
      var gameFile = Files.CurrentItem as FileBackup;
      if (gameFile != null)
      {
        if (_Container.Resolve<IMessageBoxService>().Show(Application.Current.MainWindow, string.Format("Are you sure you want to delete verion {0} of file \"{1}\"?", gameFile.Version, gameFile.Filename), "Confirm Delete", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No) == MessageBoxResult.Yes)
        {
          _FileStore.Delete(gameFile);
          OnGameFilesChanged();
        }
      }
    }

    private void ExecuteDownloadFile(object parameter)
    {
      var gameFile = Files.CurrentItem as FileBackup;
      if (gameFile != null)
      {
        if (_Container.Resolve<IMessageBoxService>().Show(Application.Current.MainWindow, "This action will overwrite your current file.  All unstored progress will be lost.\n\nAre you sure you want to continue?", "Confirm Download", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No) == MessageBoxResult.Yes)
        {
          _FileStore.Download(gameFile, gameFile.Filename);
          LocalExists = File.Exists(_Filename);
          _Container.Resolve<IMessageBoxService>().Show(Application.Current.MainWindow, string.Format(gameFile.Filename +" downloaded.", gameFile.Version, gameFile.Filename), "Download Complete", MessageBoxButton.OK, MessageBoxImage.Information);
        }
      }
    }

    private bool GameFileSelected(object parameter)
    {
      return Files != null && Files.CurrentItem as FileBackup != null;
    }

    private void OnGameFilesChanged()
    {
      Files = new CollectionView(_FileStore.Get(_Filename));
      OnPropertyChanged("Files");
      _DeleteFileCommand.RequeryCanExecute();
      _EditCommentCommand.RequeryCanExecute();
      _DownloadFileCommand.RequeryCanExecute();
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string property)
    {
      var handler = PropertyChanged;
      if (handler != null)
        handler(this, new PropertyChangedEventArgs(property));
    }
    #endregion
  }
}
